This is an Introduction to reshape2.

October 19, 2013

An Introduction to reshape2

reshape2 is an R package written by Hadley Wickham that makes it easy to transform data between wide and long formats.

What makes data wide or long?

Wide data has a column for each variable. For example, this is wide-format data:

# wide-format data
#   ozone   wind  temp
# 1 23.62 11.623 65.55
# 2 29.44 10.267 79.10
# 3 59.12  8.942 83.90
# 4 59.96  8.794 83.97

And this is long-format data:

# long-format data
#    variable  value
# 1     ozone 23.615
# 2     ozone 29.444
# 3     ozone 59.115
# 4     ozone 59.962
# 5      wind 11.623
# 6      wind 10.267
# 7      wind  8.942
# 8      wind  8.794
# 9      temp 65.548
# 10     temp 79.100
# 11     temp 83.903
# 12     temp 83.968

Long-format data has a column for possible variable types and a column for the values of those variables. Long-format data isn’t necessarily only two columns. For example, we might have ozone measurements for each day of the year. In that case, we could have another column for day. In other words, there are different levels of “longness”. The ultimate shape you want to get your data into will depend on what you are doing with it.

It turns out that you need wide-format data for some types of data analysis and long-format data for others. In reality, you need long-format data much more commonly than wide-format data. For example, ggplot2 requires long-format data (technically tidy data), plyr requires long-format data, and most modelling functions (such as lm(), glm(), and gam()) require long-format data. But people often find it easier to record their data in wide format.

The reshape2 package

reshape2 is based around two key functions: melt and cast:

melt takes wide-format data and melts it into long-format data.

cast takes long-format data and casts it into wide-format data.

Think of working with metal: if you melt metal, it drips and becomes long. If you cast it into a mould, it becomes wide.

Wide- to long-format data: the melt function

For this example we’ll work with the airquality dataset that is built into R. First we’ll change the column names to lower case to make them easier to work with. Then we’ll look at the data:

names(airquality) <- tolower(names(airquality))
head(airquality)
#   ozone solar.r wind temp month day
# 1    41     190  7.4   67     5   1
# 2    36     118  8.0   72     5   2
# 3    12     149 12.6   74     5   3
# 4    18     313 11.5   62     5   4
# 5    NA      NA 14.3   56     5   5
# 6    28      NA 14.9   66     5   6

What happens if we run the function melt with all the default argument values?

# aql:[a]ir [q]uality [l]ong format
aql <- melt(airquality) 

head(aql)
#   variable value
# 1    ozone    41
# 2    ozone    36
# 3    ozone    12
# 4    ozone    18
# 5    ozone    NA
# 6    ozone    28
tail(aql)
#     variable value
# 913      day    25
# 914      day    26
# 915      day    27
# 916      day    28
# 917      day    29
# 918      day    30

By default, melt has assumed that all columns with numeric values are variables with values. Often this is what you want. Maybe here we want to know the values of ozone, solar.r, wind, and temp for each month and day. We can do that with melt by telling it that we want month and day to be “ID variables”. ID variables are the variables that identify individual rows of data.

aql <- melt(airquality, id.vars = c("month", "day"))
head(aql)
#   month day variable value
# 1     5   1    ozone    41
# 2     5   2    ozone    36
# 3     5   3    ozone    12
# 4     5   4    ozone    18
# 5     5   5    ozone    NA
# 6     5   6    ozone    28

What if we wanted to control the column names in our long-format data? melt lets us set those too all in one step:

aql <- melt(airquality, id.vars = c("month", "day"),
  variable.name = "climate_variable", 
  value.name = "climate_value")
head(aql)
#   month day climate_variable climate_value
# 1     5   1            ozone            41
# 2     5   2            ozone            36
# 3     5   3            ozone            12
# 4     5   4            ozone            18
# 5     5   5            ozone            NA
# 6     5   6            ozone            28

Long- to wide-format data: the cast functions

Whereas going from wide- to long-format data is pretty straightforward, going from long- to wide-format data can take a bit more thought. It usually involves some head scratching and some trial and error for all but the simplest cases. Let’s go through some examples.

In reshape2 there are multiple cast functions. Since you will most commonly work with data.frame objects, we’ll explore the dcast function. (There is also acast to return a vector, matrix, or array.)

Let’s take the long-format airquality data and cast it into some different wide formats. To start with, we’ll recover the same format we started with and compare the two.

dcast uses a formula to describe the shape of the data. The arguments on the left refer to the ID variables and the arguments on the right refer to the measured variables. Coming up with the right formula can take some trial and error at first. So, if you’re stuck don’t feel bad about just experimenting with formulas. There are usually only so many ways you can write the formula.

Here, we need to tell dcast that month and day are the ID variables (we want a column for each) and that variable describes the measured variables. Since there is only one remaining column, dcast will figure out that it contains the values themselves. We could explicitly declare this with value.var. (And in some cases it will be necessary to do so.)

# airquality long format
aql <- melt(airquality, id.vars = c("month", "day"))
rbind(head(aql, 5),tail(aql, 5))

# airquality wide format
aqw <- dcast(aql, month + day ~ variable)
head(aqw)
#   month day ozone solar.r wind temp
# 1     5   1    41     190  7.4   67
# 2     5   2    36     118  8.0   72
# 3     5   3    12     149 12.6   74
# 4     5   4    18     313 11.5   62
# 5     5   5    NA      NA 14.3   56
# 6     5   6    28      NA 14.9   66


# original data
head(airquality) 
#   ozone solar.r wind temp month day
# 1    41     190  7.4   67     5   1
# 2    36     118  8.0   72     5   2
# 3    12     149 12.6   74     5   3
# 4    18     313 11.5   62     5   4
# 5    NA      NA 14.3   56     5   5
# 6    28      NA 14.9   66     5   6

So, besides re-arranging the columns, we’ve recovered our original data.

If it isn’t clear to you what just happened there, then have a look at this illustration:

Figure 1: An illustration of the dcast function. The blue shading indicates ID variables that we want to represent individual rows. The red shading represents variable names that we want to swing into column names. The grey shading represents the data values that we want to fill in the cells with.

One confusing “mistake” you might make is casting a dataset in which there is more than one value per data cell. For example, this time we won’t include day as an ID variable:

dcast(aql, month ~ variable)
#   month ozone solar.r wind temp
# 1     5    31      31   31   31
# 2     6    30      30   30   30
# 3     7    31      31   31   31
# 4     8    31      31   31   31
# 5     9    30      30   30   30

When you run this in R, you’ll notice the warning message:

# Aggregation function missing: defaulting to length

And if you look at the output, the cells are filled with the number of data rows for each month-climate combination. The numbers we’re seeing are the number of days recorded in each month. When you cast your data and there are multiple values per cell, you also need to tell dcast how to aggregate the data. For example, maybe you want to take the mean, or the median, or the sum. Let’s try the last example, but this time we’ll take the mean of the climate values. We’ll also pass the option na.rm = TRUE through the … argument to remove NA values. (The … let’s you pass on additional arguments to your fun.aggregate function, here mean.)

dcast(aql, month ~ variable, fun.aggregate = mean, 
  na.rm = TRUE)
#   month ozone solar.r   wind  temp
# 1     5 23.62   181.3 11.623 65.55
# 2     6 29.44   190.2 10.267 79.10
# 3     7 59.12   216.5  8.942 83.90
# 4     8 59.96   171.9  8.794 83.97
# 5     9 31.45   167.4 10.180 76.90

Unlike melt, there are some other fancy things you can do with dcast that I’m not covering here. It’s worth reading the help file ?dcast. For example, you can compute summaries for rows and columns, subset the columns, and fill in missing cells in one call to dcast.

Additional help

Read the package help: help(package = "reshape2")

See the reshape2 website: reshape

And read the paper on reshape: Wickham, H. (2007). Reshaping data with the reshape package. 21(12):1–20.

(But note that the paper is written for the reshape package not the reshape2 package.)

R笔记:formula和Formula

R笔记(1):formula和Formula

1.基本的R公式对象formula

在R当中,公式fomula是一个把响应变量(在左侧)和解释变量(在右侧)联系起来的对象。formula可以用在线性/一般线性模型(如lm(),glm()),树方法(如rpart())和图形表示(如coplot())以及其它一些场合(如table())。formula在这些场合中给出了关于统计模型的简洁而统一的符号模型形式y ~ model

关于formula这种处理方法的思想可能最早来自于方差分析。在 Chambers and Hastie (1993) “Statistical Models in S” 这本书当中给出了S语言(以及后来的R语言)formula的明确参考。他们把统计模型的形式分为三个部分,其中“a formula that defines the structural part of the model-that is, what data are being modeled and by what other data, in what form”。

(1)formula的例:

fit2 <- lm(weight ~ height + I(height^2), data = women)

(2)关于formula所常用的符号,参见下表(取自R in action ):

(3)创建包含很多个解释变量的公式的一种方法是使用paste():

xnam <- paste0("x", c(1:10, 15, 20:25))
(f <- as.formula(paste("y ~ ", paste(xnam, collapse = "+"))))
## y ~ x1 + x2 + x3 + x4 + x5 + x6 + x7 + x8 + x9 + x10 + x15 + 
## x20 + x21 + x22 + x23 + x24 + x25

# 或者
xnam <- paste("x", c(1:10, 15, 20:25), sep = "")
(f <- as.formula(paste("y ~ ", paste(xnam, collapse = "+"))))
## y ~ x1 + x2 + x3 + x4 + x5 + x6 + x7 + x8 + x9 + x10 + x15 + 
## x20 + x21 + x22 + x23 + x24 + x25

formula对象的细节参考:?formula

2.Fomula包

Formula包提供了关于R中模型公式的一个扩展,可以在~右侧(RHS)和(或)左侧(LHS)加入多个部分,相应的模型对象叫做Fomula。

这个包的目的是解决formula对象的一些局限:不支持多个响应变量也不方便处理由几个不同部分处理的公式。在一些R的扩展包当中用各自的方法处理这些问题,Forluma包希望给出一种统一的方法。

在形式上,Formula对象对于formula对象的扩展在于:引入新的运算符|以容纳模型的多个部分,并可将formula的运算符应用于LHS。

一个简单的例子:

library(Formula)
f1 <- y1 | y2 + y3 ~ x1 + I(x2^2) | 0 + log(x1) | x3/x4
F1 <- Formula(f1)
length(F1)
## [1] 2 3
# length()的结果说明这个Fomula的左侧有两个部分,右侧有三个部分。

关于这个包的细节可参考: Zeileis A, Croissant Y (2010). “Extended Model Formulas in R: Multiple Parts and Multiple Responses.” Journal of Statistical Software, 34(1), 1–13. http://www.jstatsoft.org/v34/i01/.

LS0tDQp0aXRsZTogIkludHJvZHVjdGlvbiB0byByZXNoYXBlMiINCm91dHB1dDogaHRtbF9ub3RlYm9vaw0KLS0tDQoNClRoaXMgaXMgYW4gW0ludHJvZHVjdGlvbiB0byByZXNoYXBlMl0oaHR0cDovL3NlYW5hbmRlcnNvbi5jYS8yMDEzLzEwLzE5L3Jlc2hhcGUuaHRtbCkuIA0KDQo+IE9jdG9iZXIgMTksIDIwMTMNCg0KIyBBbiBJbnRyb2R1Y3Rpb24gdG8gcmVzaGFwZTINCg0KW3Jlc2hhcGUyXShodHRwOi8vY3Jhbi5yLXByb2plY3Qub3JnL3dlYi9wYWNrYWdlcy9yZXNoYXBlMi9pbmRleC5odG1sKSBpcyBhbiBSIHBhY2thZ2Ugd3JpdHRlbiBieSBbSGFkbGV5IFdpY2toYW1dKGh0dHA6Ly9oYWQuY28ubnovKSB0aGF0IG1ha2VzIGl0IGVhc3kgdG8gdHJhbnNmb3JtIGRhdGEgYmV0d2VlbiB3aWRlIGFuZCBsb25nIGZvcm1hdHMuDQoNCiMjIFdoYXQgbWFrZXMgZGF0YSB3aWRlIG9yIGxvbmc/DQoNCldpZGUgZGF0YSBoYXMgYSBjb2x1bW4gZm9yIGVhY2ggdmFyaWFibGUuIEZvciBleGFtcGxlLCB0aGlzIGlzIHdpZGUtZm9ybWF0IGRhdGE6DQpgYGB7ciB3aWRlLWZvcm1hdCBkYXRhfQ0KIyB3aWRlLWZvcm1hdCBkYXRhDQojICAgb3pvbmUgICB3aW5kICB0ZW1wDQojIDEgMjMuNjIgMTEuNjIzIDY1LjU1DQojIDIgMjkuNDQgMTAuMjY3IDc5LjEwDQojIDMgNTkuMTIgIDguOTQyIDgzLjkwDQojIDQgNTkuOTYgIDguNzk0IDgzLjk3DQpgYGANCg0KQW5kIHRoaXMgaXMgbG9uZy1mb3JtYXQgZGF0YToNCmBgYHtyIGxvbmctZm9ybWF0IGRhdGF9DQojIGxvbmctZm9ybWF0IGRhdGENCiMgICAgdmFyaWFibGUgIHZhbHVlDQojIDEgICAgIG96b25lIDIzLjYxNQ0KIyAyICAgICBvem9uZSAyOS40NDQNCiMgMyAgICAgb3pvbmUgNTkuMTE1DQojIDQgICAgIG96b25lIDU5Ljk2Mg0KIyA1ICAgICAgd2luZCAxMS42MjMNCiMgNiAgICAgIHdpbmQgMTAuMjY3DQojIDcgICAgICB3aW5kICA4Ljk0Mg0KIyA4ICAgICAgd2luZCAgOC43OTQNCiMgOSAgICAgIHRlbXAgNjUuNTQ4DQojIDEwICAgICB0ZW1wIDc5LjEwMA0KIyAxMSAgICAgdGVtcCA4My45MDMNCiMgMTIgICAgIHRlbXAgODMuOTY4DQpgYGANCg0KTG9uZy1mb3JtYXQgZGF0YSBoYXMgYSBjb2x1bW4gZm9yIHBvc3NpYmxlIHZhcmlhYmxlIHR5cGVzIGFuZCBhIGNvbHVtbiBmb3IgdGhlIHZhbHVlcyBvZiB0aG9zZSB2YXJpYWJsZXMuIExvbmctZm9ybWF0IGRhdGEgaXNu4oCZdCBuZWNlc3NhcmlseSBvbmx5IHR3byBjb2x1bW5zLiBGb3IgZXhhbXBsZSwgd2UgbWlnaHQgaGF2ZSBvem9uZSBtZWFzdXJlbWVudHMgZm9yIGVhY2ggZGF5IG9mIHRoZSB5ZWFyLiBJbiB0aGF0IGNhc2UsIHdlIGNvdWxkIGhhdmUgYW5vdGhlciBjb2x1bW4gZm9yIGRheS4gSW4gb3RoZXIgd29yZHMsIHRoZXJlIGFyZSBkaWZmZXJlbnQgbGV2ZWxzIG9mIOKAnGxvbmduZXNz4oCdLiBUaGUgdWx0aW1hdGUgc2hhcGUgeW91IHdhbnQgdG8gZ2V0IHlvdXIgZGF0YSBpbnRvIHdpbGwgZGVwZW5kIG9uIHdoYXQgeW91IGFyZSBkb2luZyB3aXRoIGl0Lg0KDQpJdCB0dXJucyBvdXQgdGhhdCB5b3UgbmVlZCB3aWRlLWZvcm1hdCBkYXRhIGZvciBzb21lIHR5cGVzIG9mIGRhdGEgYW5hbHlzaXMgYW5kIGxvbmctZm9ybWF0IGRhdGEgZm9yIG90aGVycy4gSW4gcmVhbGl0eSwgeW91IG5lZWQgbG9uZy1mb3JtYXQgZGF0YSBtdWNoIG1vcmUgY29tbW9ubHkgdGhhbiB3aWRlLWZvcm1hdCBkYXRhLiBGb3IgZXhhbXBsZSwgZ2dwbG90MiByZXF1aXJlcyBsb25nLWZvcm1hdCBkYXRhICh0ZWNobmljYWxseSB0aWR5IGRhdGEpLCBwbHlyIHJlcXVpcmVzIGxvbmctZm9ybWF0IGRhdGEsIGFuZCBtb3N0IG1vZGVsbGluZyBmdW5jdGlvbnMgKHN1Y2ggYXMgbG0oKSwgZ2xtKCksIGFuZCBnYW0oKSkgcmVxdWlyZSBsb25nLWZvcm1hdCBkYXRhLiBCdXQgcGVvcGxlIG9mdGVuIGZpbmQgaXQgZWFzaWVyIHRvIHJlY29yZCB0aGVpciBkYXRhIGluIHdpZGUgZm9ybWF0Lg0KDQojIyBUaGUgcmVzaGFwZTIgcGFja2FnZQ0KDQpgcmVzaGFwZTJgIGlzIGJhc2VkIGFyb3VuZCB0d28ga2V5IGZ1bmN0aW9uczogYG1lbHRgIGFuZCBgY2FzdGA6DQoNCmBtZWx0YCB0YWtlcyB3aWRlLWZvcm1hdCBkYXRhIGFuZCBtZWx0cyBpdCBpbnRvIGxvbmctZm9ybWF0IGRhdGEuDQoNCmBjYXN0YCB0YWtlcyBsb25nLWZvcm1hdCBkYXRhIGFuZCBjYXN0cyBpdCBpbnRvIHdpZGUtZm9ybWF0IGRhdGEuDQoNClRoaW5rIG9mIHdvcmtpbmcgd2l0aCBtZXRhbDogaWYgeW91IG1lbHQgbWV0YWwsIGl0IGRyaXBzIGFuZCBiZWNvbWVzIGxvbmcuIElmIHlvdSBjYXN0IGl0IGludG8gYSBtb3VsZCwgaXQgYmVjb21lcyB3aWRlLg0KDQojIyBXaWRlLSB0byBsb25nLWZvcm1hdCBkYXRhOiB0aGUgbWVsdCBmdW5jdGlvbg0KDQpGb3IgdGhpcyBleGFtcGxlIHdl4oCZbGwgd29yayB3aXRoIHRoZSBhaXJxdWFsaXR5IGRhdGFzZXQgdGhhdCBpcyBidWlsdCBpbnRvIFIuIEZpcnN0IHdl4oCZbGwgY2hhbmdlIHRoZSBjb2x1bW4gbmFtZXMgdG8gbG93ZXIgY2FzZSB0byBtYWtlIHRoZW0gZWFzaWVyIHRvIHdvcmsgd2l0aC4gVGhlbiB3ZeKAmWxsIGxvb2sgYXQgdGhlIGRhdGE6DQoNCmBgYHtyIHJlc2hhcGUgYWlycXVhbGl0eSBkYXRhIGV4YW1wbGV9DQpuYW1lcyhhaXJxdWFsaXR5KSA8LSB0b2xvd2VyKG5hbWVzKGFpcnF1YWxpdHkpKQ0KaGVhZChhaXJxdWFsaXR5KQ0KIyAgIG96b25lIHNvbGFyLnIgd2luZCB0ZW1wIG1vbnRoIGRheQ0KIyAxICAgIDQxICAgICAxOTAgIDcuNCAgIDY3ICAgICA1ICAgMQ0KIyAyICAgIDM2ICAgICAxMTggIDguMCAgIDcyICAgICA1ICAgMg0KIyAzICAgIDEyICAgICAxNDkgMTIuNiAgIDc0ICAgICA1ICAgMw0KIyA0ICAgIDE4ICAgICAzMTMgMTEuNSAgIDYyICAgICA1ICAgNA0KIyA1ICAgIE5BICAgICAgTkEgMTQuMyAgIDU2ICAgICA1ICAgNQ0KIyA2ICAgIDI4ICAgICAgTkEgMTQuOSAgIDY2ICAgICA1ICAgNg0KYGBgDQoNCldoYXQgaGFwcGVucyBpZiB3ZSBydW4gdGhlIGZ1bmN0aW9uIG1lbHQgd2l0aCBhbGwgdGhlIGRlZmF1bHQgYXJndW1lbnQgdmFsdWVzPw0KDQpgYGB7ciByZXNoYXBlIG1lbHQgd2l0aCBhbGwgdGhlIGRlZmF1bHQgYXJndW1lbnQgdmFsdWVzfQ0KIyBhcWw6W2FdaXIgW3FddWFsaXR5IFtsXW9uZyBmb3JtYXQNCmFxbCA8LSBtZWx0KGFpcnF1YWxpdHkpIA0KDQpoZWFkKGFxbCkNCiMgICB2YXJpYWJsZSB2YWx1ZQ0KIyAxICAgIG96b25lICAgIDQxDQojIDIgICAgb3pvbmUgICAgMzYNCiMgMyAgICBvem9uZSAgICAxMg0KIyA0ICAgIG96b25lICAgIDE4DQojIDUgICAgb3pvbmUgICAgTkENCiMgNiAgICBvem9uZSAgICAyOA0KdGFpbChhcWwpDQojICAgICB2YXJpYWJsZSB2YWx1ZQ0KIyA5MTMgICAgICBkYXkgICAgMjUNCiMgOTE0ICAgICAgZGF5ICAgIDI2DQojIDkxNSAgICAgIGRheSAgICAyNw0KIyA5MTYgICAgICBkYXkgICAgMjgNCiMgOTE3ICAgICAgZGF5ICAgIDI5DQojIDkxOCAgICAgIGRheSAgICAzMA0KYGBgDQoNCkJ5IGRlZmF1bHQsIG1lbHQgaGFzIGFzc3VtZWQgdGhhdCBhbGwgY29sdW1ucyB3aXRoIG51bWVyaWMgdmFsdWVzIGFyZSB2YXJpYWJsZXMgd2l0aCB2YWx1ZXMuIE9mdGVuIHRoaXMgaXMgd2hhdCB5b3Ugd2FudC4gTWF5YmUgaGVyZSB3ZSB3YW50IHRvIGtub3cgdGhlIHZhbHVlcyBvZiBvem9uZSwgc29sYXIuciwgd2luZCwgYW5kIHRlbXAgZm9yIGVhY2ggbW9udGggYW5kIGRheS4gV2UgY2FuIGRvIHRoYXQgd2l0aCBtZWx0IGJ5IHRlbGxpbmcgaXQgdGhhdCB3ZSB3YW50IG1vbnRoIGFuZCBkYXkgdG8gYmUg4oCcSUQgdmFyaWFibGVz4oCdLiBJRCB2YXJpYWJsZXMgYXJlIHRoZSB2YXJpYWJsZXMgdGhhdCBpZGVudGlmeSBpbmRpdmlkdWFsIHJvd3Mgb2YgZGF0YS4NCg0KYGBge3IgcmVzaGFwZSBpZGVudGlmeSBpbmRpdmlkdWFsIHJvd3MsIGtlZXAgY29sdW1ufQ0KYXFsIDwtIG1lbHQoYWlycXVhbGl0eSwgaWQudmFycyA9IGMoIm1vbnRoIiwgImRheSIpKQ0KaGVhZChhcWwpDQojICAgbW9udGggZGF5IHZhcmlhYmxlIHZhbHVlDQojIDEgICAgIDUgICAxICAgIG96b25lICAgIDQxDQojIDIgICAgIDUgICAyICAgIG96b25lICAgIDM2DQojIDMgICAgIDUgICAzICAgIG96b25lICAgIDEyDQojIDQgICAgIDUgICA0ICAgIG96b25lICAgIDE4DQojIDUgICAgIDUgICA1ICAgIG96b25lICAgIE5BDQojIDYgICAgIDUgICA2ICAgIG96b25lICAgIDI4DQpgYGANCg0KDQpXaGF0IGlmIHdlIHdhbnRlZCB0byBjb250cm9sIHRoZSBjb2x1bW4gbmFtZXMgaW4gb3VyIGxvbmctZm9ybWF0IGRhdGE/IG1lbHQgbGV0cyB1cyBzZXQgdGhvc2UgdG9vIGFsbCBpbiBvbmUgc3RlcDoNCmBgYHtyIHJlbmFtZSBjb2x1bW4gbmFtZX0NCmFxbCA8LSBtZWx0KGFpcnF1YWxpdHksIGlkLnZhcnMgPSBjKCJtb250aCIsICJkYXkiKSwNCiAgdmFyaWFibGUubmFtZSA9ICJjbGltYXRlX3ZhcmlhYmxlIiwgDQogIHZhbHVlLm5hbWUgPSAiY2xpbWF0ZV92YWx1ZSIpDQpoZWFkKGFxbCkNCiMgICBtb250aCBkYXkgY2xpbWF0ZV92YXJpYWJsZSBjbGltYXRlX3ZhbHVlDQojIDEgICAgIDUgICAxICAgICAgICAgICAgb3pvbmUgICAgICAgICAgICA0MQ0KIyAyICAgICA1ICAgMiAgICAgICAgICAgIG96b25lICAgICAgICAgICAgMzYNCiMgMyAgICAgNSAgIDMgICAgICAgICAgICBvem9uZSAgICAgICAgICAgIDEyDQojIDQgICAgIDUgICA0ICAgICAgICAgICAgb3pvbmUgICAgICAgICAgICAxOA0KIyA1ICAgICA1ICAgNSAgICAgICAgICAgIG96b25lICAgICAgICAgICAgTkENCiMgNiAgICAgNSAgIDYgICAgICAgICAgICBvem9uZSAgICAgICAgICAgIDI4DQpgYGANCg0KIyMgTG9uZy0gdG8gd2lkZS1mb3JtYXQgZGF0YTogdGhlIGNhc3QgZnVuY3Rpb25zDQoNCldoZXJlYXMgZ29pbmcgZnJvbSB3aWRlLSB0byBsb25nLWZvcm1hdCBkYXRhIGlzIHByZXR0eSBzdHJhaWdodGZvcndhcmQsIGdvaW5nIGZyb20gbG9uZy0gdG8gd2lkZS1mb3JtYXQgZGF0YSBjYW4gdGFrZSBhIGJpdCBtb3JlIHRob3VnaHQuIEl0IHVzdWFsbHkgaW52b2x2ZXMgc29tZSBoZWFkIHNjcmF0Y2hpbmcgYW5kIHNvbWUgdHJpYWwgYW5kIGVycm9yIGZvciBhbGwgYnV0IHRoZSBzaW1wbGVzdCBjYXNlcy4gTGV04oCZcyBnbyB0aHJvdWdoIHNvbWUgZXhhbXBsZXMuDQoNCkluIHJlc2hhcGUyIHRoZXJlIGFyZSBtdWx0aXBsZSBjYXN0IGZ1bmN0aW9ucy4gU2luY2UgeW91IHdpbGwgbW9zdCBjb21tb25seSB3b3JrIHdpdGggYGRhdGEuZnJhbWVgIG9iamVjdHMsIHdl4oCZbGwgZXhwbG9yZSB0aGUgYGRjYXN0YCBmdW5jdGlvbi4gKFRoZXJlIGlzIGFsc28gYGFjYXN0YCB0byByZXR1cm4gYSB2ZWN0b3IsIG1hdHJpeCwgb3IgYXJyYXkuKQ0KDQpMZXTigJlzIHRha2UgdGhlIGxvbmctZm9ybWF0IGFpcnF1YWxpdHkgZGF0YSBhbmQgY2FzdCBpdCBpbnRvIHNvbWUgZGlmZmVyZW50IHdpZGUgZm9ybWF0cy4gVG8gc3RhcnQgd2l0aCwgd2XigJlsbCByZWNvdmVyIHRoZSBzYW1lIGZvcm1hdCB3ZSBzdGFydGVkIHdpdGggYW5kIGNvbXBhcmUgdGhlIHR3by4NCg0KYGRjYXN0YCB1c2VzIGEgZm9ybXVsYSB0byBkZXNjcmliZSB0aGUgc2hhcGUgb2YgdGhlIGRhdGEuIFRoZSBhcmd1bWVudHMgb24gdGhlIGxlZnQgcmVmZXIgdG8gdGhlIElEIHZhcmlhYmxlcyBhbmQgdGhlIGFyZ3VtZW50cyBvbiB0aGUgcmlnaHQgcmVmZXIgdG8gdGhlIG1lYXN1cmVkIHZhcmlhYmxlcy4gQ29taW5nIHVwIHdpdGggdGhlIHJpZ2h0IGZvcm11bGEgY2FuIHRha2Ugc29tZSB0cmlhbCBhbmQgZXJyb3IgYXQgZmlyc3QuIFNvLCBpZiB5b3XigJlyZSBzdHVjayBkb27igJl0IGZlZWwgYmFkIGFib3V0IGp1c3QgZXhwZXJpbWVudGluZyB3aXRoIGZvcm11bGFzLiBUaGVyZSBhcmUgdXN1YWxseSBvbmx5IHNvIG1hbnkgd2F5cyB5b3UgY2FuIHdyaXRlIHRoZSBmb3JtdWxhLg0KDQpIZXJlLCB3ZSBuZWVkIHRvIHRlbGwgYGRjYXN0YCB0aGF0IG1vbnRoIGFuZCBkYXkgYXJlIHRoZSBJRCB2YXJpYWJsZXMgKHdlIHdhbnQgYSBjb2x1bW4gZm9yIGVhY2gpIGFuZCB0aGF0IHZhcmlhYmxlIGRlc2NyaWJlcyB0aGUgbWVhc3VyZWQgdmFyaWFibGVzLiBTaW5jZSB0aGVyZSBpcyBvbmx5IG9uZSByZW1haW5pbmcgY29sdW1uLCBgZGNhc3RgIHdpbGwgZmlndXJlIG91dCB0aGF0IGl0IGNvbnRhaW5zIHRoZSB2YWx1ZXMgdGhlbXNlbHZlcy4gV2UgY291bGQgZXhwbGljaXRseSBkZWNsYXJlIHRoaXMgd2l0aCBgdmFsdWUudmFyYC4gKEFuZCBpbiBzb21lIGNhc2VzIGl0IHdpbGwgYmUgbmVjZXNzYXJ5IHRvIGRvIHNvLikNCg0KYGBge3IgZGNhc3QgZGVtb30NCiMgYWlycXVhbGl0eSBsb25nIGZvcm1hdA0KYXFsIDwtIG1lbHQoYWlycXVhbGl0eSwgaWQudmFycyA9IGMoIm1vbnRoIiwgImRheSIpKQ0KcmJpbmQoaGVhZChhcWwsIDUpLHRhaWwoYXFsLCA1KSkNCg0KIyBhaXJxdWFsaXR5IHdpZGUgZm9ybWF0DQphcXcgPC0gZGNhc3QoYXFsLCBtb250aCArIGRheSB+IHZhcmlhYmxlKQ0KaGVhZChhcXcpDQojICAgbW9udGggZGF5IG96b25lIHNvbGFyLnIgd2luZCB0ZW1wDQojIDEgICAgIDUgICAxICAgIDQxICAgICAxOTAgIDcuNCAgIDY3DQojIDIgICAgIDUgICAyICAgIDM2ICAgICAxMTggIDguMCAgIDcyDQojIDMgICAgIDUgICAzICAgIDEyICAgICAxNDkgMTIuNiAgIDc0DQojIDQgICAgIDUgICA0ICAgIDE4ICAgICAzMTMgMTEuNSAgIDYyDQojIDUgICAgIDUgICA1ICAgIE5BICAgICAgTkEgMTQuMyAgIDU2DQojIDYgICAgIDUgICA2ICAgIDI4ICAgICAgTkEgMTQuOSAgIDY2DQoNCg0KIyBvcmlnaW5hbCBkYXRhDQpoZWFkKGFpcnF1YWxpdHkpIA0KIyAgIG96b25lIHNvbGFyLnIgd2luZCB0ZW1wIG1vbnRoIGRheQ0KIyAxICAgIDQxICAgICAxOTAgIDcuNCAgIDY3ICAgICA1ICAgMQ0KIyAyICAgIDM2ICAgICAxMTggIDguMCAgIDcyICAgICA1ICAgMg0KIyAzICAgIDEyICAgICAxNDkgMTIuNiAgIDc0ICAgICA1ICAgMw0KIyA0ICAgIDE4ICAgICAzMTMgMTEuNSAgIDYyICAgICA1ICAgNA0KIyA1ICAgIE5BICAgICAgTkEgMTQuMyAgIDU2ICAgICA1ICAgNQ0KIyA2ICAgIDI4ICAgICAgTkEgMTQuOSAgIDY2ICAgICA1ICAgNg0KYGBgDQoNClNvLCBiZXNpZGVzIHJlLWFycmFuZ2luZyB0aGUgY29sdW1ucywgd2XigJl2ZSByZWNvdmVyZWQgb3VyIG9yaWdpbmFsIGRhdGEuDQoNCklmIGl0IGlzbuKAmXQgY2xlYXIgdG8geW91IHdoYXQganVzdCBoYXBwZW5lZCB0aGVyZSwgdGhlbiBoYXZlIGEgbG9vayBhdCB0aGlzIGlsbHVzdHJhdGlvbjoNCg0KDQpGaWd1cmUgMTogQW4gaWxsdXN0cmF0aW9uIG9mIHRoZSBgZGNhc3RgIGZ1bmN0aW9uLiBUaGUgYmx1ZSBzaGFkaW5nIGluZGljYXRlcyBJRCB2YXJpYWJsZXMgdGhhdCB3ZSB3YW50IHRvIHJlcHJlc2VudCBpbmRpdmlkdWFsIHJvd3MuIFRoZSByZWQgc2hhZGluZyByZXByZXNlbnRzIHZhcmlhYmxlIG5hbWVzIHRoYXQgd2Ugd2FudCB0byBzd2luZyBpbnRvIGNvbHVtbiBuYW1lcy4gVGhlIGdyZXkgc2hhZGluZyByZXByZXNlbnRzIHRoZSBkYXRhIHZhbHVlcyB0aGF0IHdlIHdhbnQgdG8gZmlsbCBpbiB0aGUgY2VsbHMgd2l0aC4NCg0KT25lIGNvbmZ1c2luZyDigJxtaXN0YWtl4oCdIHlvdSBtaWdodCBtYWtlIGlzIGNhc3RpbmcgYSBkYXRhc2V0IGluIHdoaWNoIHRoZXJlIGlzIG1vcmUgdGhhbiBvbmUgdmFsdWUgcGVyIGRhdGEgY2VsbC4gRm9yIGV4YW1wbGUsIHRoaXMgdGltZSB3ZSB3b27igJl0IGluY2x1ZGUgZGF5IGFzIGFuIElEIHZhcmlhYmxlOg0KYGBge3IgZGNhc3QgZGVtbyAyfQ0KZGNhc3QoYXFsLCBtb250aCB+IHZhcmlhYmxlKQ0KIyAgIG1vbnRoIG96b25lIHNvbGFyLnIgd2luZCB0ZW1wDQojIDEgICAgIDUgICAgMzEgICAgICAzMSAgIDMxICAgMzENCiMgMiAgICAgNiAgICAzMCAgICAgIDMwICAgMzAgICAzMA0KIyAzICAgICA3ICAgIDMxICAgICAgMzEgICAzMSAgIDMxDQojIDQgICAgIDggICAgMzEgICAgICAzMSAgIDMxICAgMzENCiMgNSAgICAgOSAgICAzMCAgICAgIDMwICAgMzAgICAzMA0KDQpgYGANCg0KDQpXaGVuIHlvdSBydW4gdGhpcyBpbiBSLCB5b3XigJlsbCBub3RpY2UgdGhlIHdhcm5pbmcgbWVzc2FnZToNCg0KYCMgQWdncmVnYXRpb24gZnVuY3Rpb24gbWlzc2luZzogZGVmYXVsdGluZyB0byBsZW5ndGhgDQoNCkFuZCBpZiB5b3UgbG9vayBhdCB0aGUgb3V0cHV0LCB0aGUgY2VsbHMgYXJlIGZpbGxlZCB3aXRoIHRoZSBudW1iZXIgb2YgZGF0YSByb3dzIGZvciBlYWNoIG1vbnRoLWNsaW1hdGUgY29tYmluYXRpb24uIFRoZSBudW1iZXJzIHdl4oCZcmUgc2VlaW5nIGFyZSB0aGUgbnVtYmVyIG9mIGRheXMgcmVjb3JkZWQgaW4gZWFjaCBtb250aC4gV2hlbiB5b3UgYGNhc3RgIHlvdXIgZGF0YSBhbmQgdGhlcmUgYXJlIG11bHRpcGxlIHZhbHVlcyBwZXIgY2VsbCwgeW91IGFsc28gbmVlZCB0byB0ZWxsIGRjYXN0IGhvdyB0byBhZ2dyZWdhdGUgdGhlIGRhdGEuIEZvciBleGFtcGxlLCBtYXliZSB5b3Ugd2FudCB0byB0YWtlIHRoZSBgbWVhbmAsIG9yIHRoZSBgbWVkaWFuYCwgb3IgdGhlIGBzdW1gLiBMZXTigJlzIHRyeSB0aGUgbGFzdCBleGFtcGxlLCBidXQgdGhpcyB0aW1lIHdl4oCZbGwgdGFrZSB0aGUgbWVhbiBvZiB0aGUgY2xpbWF0ZSB2YWx1ZXMuIFdl4oCZbGwgYWxzbyBwYXNzIHRoZSBvcHRpb24gYG5hLnJtID0gVFJVRWAgdGhyb3VnaCB0aGUgLi4uIGFyZ3VtZW50IHRvIHJlbW92ZSBOQSB2YWx1ZXMuIChUaGUgLi4uIGxldOKAmXMgeW91IHBhc3Mgb24gYWRkaXRpb25hbCBhcmd1bWVudHMgdG8geW91ciBgZnVuLmFnZ3JlZ2F0ZWAgZnVuY3Rpb24sIGhlcmUgYG1lYW5gLikNCg0KYGBge3IgZGNhc3QgYWdncmVnYXRlIGZ1bmN0aW9ufQ0KZGNhc3QoYXFsLCBtb250aCB+IHZhcmlhYmxlLCBmdW4uYWdncmVnYXRlID0gbWVhbiwgDQogIG5hLnJtID0gVFJVRSkNCiMgICBtb250aCBvem9uZSBzb2xhci5yICAgd2luZCAgdGVtcA0KIyAxICAgICA1IDIzLjYyICAgMTgxLjMgMTEuNjIzIDY1LjU1DQojIDIgICAgIDYgMjkuNDQgICAxOTAuMiAxMC4yNjcgNzkuMTANCiMgMyAgICAgNyA1OS4xMiAgIDIxNi41ICA4Ljk0MiA4My45MA0KIyA0ICAgICA4IDU5Ljk2ICAgMTcxLjkgIDguNzk0IDgzLjk3DQojIDUgICAgIDkgMzEuNDUgICAxNjcuNCAxMC4xODAgNzYuOTANCmBgYA0KDQoNClVubGlrZSBtZWx0LCB0aGVyZSBhcmUgc29tZSBvdGhlciBmYW5jeSB0aGluZ3MgeW91IGNhbiBkbyB3aXRoIGRjYXN0IHRoYXQgSeKAmW0gbm90IGNvdmVyaW5nIGhlcmUuIEl04oCZcyB3b3J0aCByZWFkaW5nIHRoZSBoZWxwIGZpbGUgP2RjYXN0LiBGb3IgZXhhbXBsZSwgeW91IGNhbiBjb21wdXRlIHN1bW1hcmllcyBmb3Igcm93cyBhbmQgY29sdW1ucywgc3Vic2V0IHRoZSBjb2x1bW5zLCBhbmQgZmlsbCBpbiBtaXNzaW5nIGNlbGxzIGluIG9uZSBjYWxsIHRvIGRjYXN0Lg0KDQojIyBBZGRpdGlvbmFsIGhlbHANCg0KUmVhZCB0aGUgcGFja2FnZSBoZWxwOiBgaGVscChwYWNrYWdlID0gInJlc2hhcGUyIilgDQoNClNlZSB0aGUgcmVzaGFwZTIgd2Vic2l0ZTogW3Jlc2hhcGVdKGh0dHA6Ly9oYWQuY28ubnovcmVzaGFwZS8pDQoNCkFuZCByZWFkIHRoZSBwYXBlciBvbiByZXNoYXBlOiBXaWNraGFtLCBILiAoMjAwNykuIFtSZXNoYXBpbmcgZGF0YSB3aXRoIHRoZSByZXNoYXBlIHBhY2thZ2UuIDIxKDEyKTox4oCTMjAuXShodHRwOi8vd3d3LmpzdGF0c29mdC5vcmcvdjIxL2kxMikNCg0KKEJ1dCBub3RlIHRoYXQgdGhlIHBhcGVyIGlzIHdyaXR0ZW4gZm9yIHRoZSByZXNoYXBlIHBhY2thZ2Ugbm90IHRoZSByZXNoYXBlMiBwYWNrYWdlLikNCg0KIyMgUueslOiusO+8mmZvcm11bGHlkoxGb3JtdWxhDQoNClLnrJTorrDvvIgx77yJ77yaZm9ybXVsYeWSjEZvcm11bGENCg0KIyMjIDEu5Z+65pys55qEUuWFrOW8j+WvueixoWZvcm11bGENCg0K5ZyoUuW9k+S4re+8jOWFrOW8j2ZvbXVsYeaYr+S4gOS4quaKiuWTjeW6lOWPmOmHj++8iOWcqH7lt6bkvqfvvInlkozop6Pph4rlj5jph4/vvIjlnKh+5Y+z5L6n77yJ6IGU57O76LW35p2l55qE5a+56LGh44CCZm9ybXVsYeWPr+S7peeUqOWcqOe6v+aApy/kuIDoiKznur/mgKfmqKHlnovvvIjlpoJsbSgpLGdsbSgp77yJ77yM5qCR5pa55rOV77yI5aaCcnBhcnQoKe+8ieWSjOWbvuW9ouihqOekuu+8iOWmgmNvcGxvdCgp77yJ5Lul5Y+K5YW25a6D5LiA5Lqb5Zy65ZCI77yI5aaCdGFibGUoKe+8ieOAgmZvcm11bGHlnKjov5nkupvlnLrlkIjkuK3nu5nlh7rkuoblhbPkuo7nu5/orqHmqKHlnovnmoTnroDmtIHogIznu5/kuIDnmoTnrKblj7fmqKHlnovlvaLlvI9geSB+IG1vZGVsYOOAgg0KDQrlhbPkuo5mb3JtdWxh6L+Z56eN5aSE55CG5pa55rOV55qE5oCd5oOz5Y+v6IO95pyA5pep5p2l6Ieq5LqO5pa55beu5YiG5p6Q44CC5ZyoIENoYW1iZXJzIGFuZCBIYXN0aWUgKDE5OTMpIOKAnFN0YXRpc3RpY2FsIE1vZGVscyBpbiBT4oCdIOi/meacrOS5puW9k+S4ree7meWHuuS6hlPor63oqIDvvIjku6Xlj4rlkI7mnaXnmoRS6K+t6KiA77yJZm9ybXVsYeeahOaYjuehruWPguiAg+OAguS7luS7rOaKiue7n+iuoeaooeWei+eahOW9ouW8j+WIhuS4uuS4ieS4qumDqOWIhu+8jOWFtuS4reKAnGEgZm9ybXVsYSB0aGF0IGRlZmluZXMgdGhlIHN0cnVjdHVyYWwgcGFydCBvZiB0aGUgbW9kZWwtdGhhdCBpcywgd2hhdCBkYXRhIGFyZSBiZWluZyBtb2RlbGVkIGFuZCBieSB3aGF0IG90aGVyIGRhdGEsIGluIHdoYXQgZm9ybeKAneOAgg0KDQrvvIgx77yJZm9ybXVsYeeahOS+i++8mg0KDQpgYGB7ciBmb3JtdWxhfQ0KZml0MiA8LSBsbSh3ZWlnaHQgfiBoZWlnaHQgKyBJKGhlaWdodF4yKSwgZGF0YSA9IHdvbWVuKQ0KYGBgDQoNCu+8iDLvvInlhbPkuo5mb3JtdWxh5omA5bi455So55qE56ym5Y+377yM5Y+C6KeB5LiL6KGo77yI5Y+W6IeqUiBpbiBhY3Rpb24g77yJOg0KDQrvvIgz77yJ5Yib5bu65YyF5ZCr5b6I5aSa5Liq6Kej6YeK5Y+Y6YeP55qE5YWs5byP55qE5LiA56eN5pa55rOV5piv5L2/55SocGFzdGXvvIjvvInvvJoNCg0KYGBge3IgZm9ybXVsYSBjb25zdHJ1Y3Rpb259DQp4bmFtIDwtIHBhc3RlMCgieCIsIGMoMToxMCwgMTUsIDIwOjI1KSkNCihmIDwtIGFzLmZvcm11bGEocGFzdGUoInkgfiAiLCBwYXN0ZSh4bmFtLCBjb2xsYXBzZSA9ICIrIikpKSkNCiMjIHkgfiB4MSArIHgyICsgeDMgKyB4NCArIHg1ICsgeDYgKyB4NyArIHg4ICsgeDkgKyB4MTAgKyB4MTUgKyANCiMjIHgyMCArIHgyMSArIHgyMiArIHgyMyArIHgyNCArIHgyNQ0KDQojIOaIluiAhQ0KeG5hbSA8LSBwYXN0ZSgieCIsIGMoMToxMCwgMTUsIDIwOjI1KSwgc2VwID0gIiIpDQooZiA8LSBhcy5mb3JtdWxhKHBhc3RlKCJ5IH4gIiwgcGFzdGUoeG5hbSwgY29sbGFwc2UgPSAiKyIpKSkpDQojIyB5IH4geDEgKyB4MiArIHgzICsgeDQgKyB4NSArIHg2ICsgeDcgKyB4OCArIHg5ICsgeDEwICsgeDE1ICsgDQojIyB4MjAgKyB4MjEgKyB4MjIgKyB4MjMgKyB4MjQgKyB4MjUNCmBgYA0KDQpmb3JtdWxh5a+56LGh55qE57uG6IqC5Y+C6ICD77yaP2Zvcm11bGENCg0KIyMjIDIuRm9tdWxh5YyFDQoNCkZvcm11bGHljIXmj5DkvpvkuoblhbPkuo5S5Lit5qih5Z6L5YWs5byP55qE5LiA5Liq5omp5bGV77yM5Y+v5Lul5ZyofuWPs+S+pyhSSFMp5ZKM77yI5oiW77yJ5bem5L6nKExIUynliqDlhaXlpJrkuKrpg6jliIbvvIznm7jlupTnmoTmqKHlnovlr7nosaHlj6vlgZpGb211bGHjgIINCg0K6L+Z5Liq5YyF55qE55uu55qE5piv6Kej5YazZm9ybXVsYeWvueixoeeahOS4gOS6m+WxgOmZkO+8muS4jeaUr+aMgeWkmuS4quWTjeW6lOWPmOmHj+S5n+S4jeaWueS+v+WkhOeQhueUseWHoOS4quS4jeWQjOmDqOWIhuWkhOeQhueahOWFrOW8j+OAguWcqOS4gOS6m1LnmoTmianlsZXljIXlvZPkuK3nlKjlkIToh6rnmoTmlrnms5XlpITnkIbov5nkupvpl67popjvvIxGb3JsdW1h5YyF5biM5pyb57uZ5Ye65LiA56eN57uf5LiA55qE5pa55rOV44CCDQoNCuWcqOW9ouW8j+S4iu+8jEZvcm11bGHlr7nosaHlr7nkuo5mb3JtdWxh5a+56LGh55qE5omp5bGV5Zyo5LqO77ya5byV5YWl5paw55qE6L+Q566X56ymfOS7peWuuee6s+aooeWei+eahOWkmuS4qumDqOWIhu+8jOW5tuWPr+WwhmZvcm11bGHnmoTov5DnrpfnrKblupTnlKjkuo5MSFPjgIINCg0K5LiA5Liq566A5Y2V55qE5L6L5a2Q77yaDQpgYGB7ciBGb3JtdWxhIHBhY2thZ2V9DQpsaWJyYXJ5KEZvcm11bGEpDQpmMSA8LSB5MSB8IHkyICsgeTMgfiB4MSArIEkoeDJeMikgfCAwICsgbG9nKHgxKSB8IHgzL3g0DQpGMSA8LSBGb3JtdWxhKGYxKQ0KbGVuZ3RoKEYxKQ0KIyMgWzFdIDIgMw0KIyBsZW5ndGgoKeeahOe7k+aenOivtOaYjui/meS4qkZvbXVsYeeahOW3puS+p+acieS4pOS4qumDqOWIhu+8jOWPs+S+p+acieS4ieS4qumDqOWIhuOAgg0KYGBgDQoNCg0K5YWz5LqO6L+Z5Liq5YyF55qE57uG6IqC5Y+v5Y+C6ICD77yaIFplaWxlaXMgQSwgQ3JvaXNzYW50IFkgKDIwMTApLiDigJxFeHRlbmRlZCBNb2RlbCBGb3JtdWxhcyBpbiBSOiBNdWx0aXBsZSBQYXJ0cyBhbmQgTXVsdGlwbGUgUmVzcG9uc2VzLuKAnSBKb3VybmFsIG9mIFN0YXRpc3RpY2FsIFNvZnR3YXJlLCAzNCgxKSwgMeKAkzEzLiBodHRwOi8vd3d3LmpzdGF0c29mdC5vcmcvdjM0L2kwMS8u